#include "preHeader.h"
#include "Session/InstancePacketHandler.h"
#include "Session/DBPServerMgr.h"
#include "Map/MapInstance.h"

int InstancePacketHandler::HandleInitializeInstance(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	pInstance->GetHook()->InitPlayArgs(pck.CastReadableStringView());
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleCharacterTeleportBeginEnterInstanceCancel(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto playerGuid = GetGuidFromValue((u16)gsIdx, pck.Read<uint64>());
	pInstance->RemovePendingEnterPlayer(playerGuid, true);
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleCharacterEnterMap(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto tpInfo = std::make_shared<PlayerTeleportInfo>();
	LoadFromINetStream(*tpInfo, pck);

	NetPacket rpcReqPck(CDBP_LOAD_ONE_PLAYER_INSTANCE);
	rpcReqPck << GetGuidFromValue(tpInfo->playerGuid).UID;
	DBPSession(gsIdx).RPCInvoke(rpcReqPck, [=](INetStream& pck, int32 err, bool) {
		auto playerGuid = GetGuidFromValue((u16)gsIdx, tpInfo->playerGuid);
		auto isSucc = pInstance->TryPlayerEnterMap(playerGuid, *tpInfo, pck, err);
		pInstance->SendPlayerEnterMapResp(isSucc, playerGuid);
	}, pInstance);

	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleCharacterLogoutGame(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto playerGuid = GetGuidFromValue((u16)gsIdx, pck.Read<uint64>());
	pInstance->LogoutPlayer(playerGuid);
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleTeamInfo(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	pInstance->GetMapTeamManager().LoadTeamFromGSPacket(pck, (u16)gsIdx);
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleTeamMemberAdd(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto pTeam = pInstance->GetMapTeamManager().GetTeam((u16)gsIdx, pck.Read<uint32>());
	if (pTeam != NULL) {
		auto playerGuid = GetGuidFromValue((u16)gsIdx, pck.Read<uint64>());
		auto pPlayer = pInstance->GetAvailablePlayer(playerGuid);
		if (pPlayer != NULL) {
			pPlayer->SetTeam(pTeam);
		}
	}
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleTeamMemberQuit(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto playerGuid = GetGuidFromValue((u16)gsIdx, pck.Read<uint64>());
	auto pPlayer = pInstance->GetAvailablePlayer(playerGuid);
	if (pPlayer != NULL) {
		pInstance->RemoveTeamMember(pPlayer);
	}
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleTeamLeaderChange(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	auto pTeam = pInstance->GetMapTeamManager().GetTeam((u16)gsIdx, pck.Read<uint32>());
	if (pTeam != NULL) {
		auto playerGuid = GetGuidFromValue((u16)gsIdx, pck.Read<uint64>());
		auto playerName = pck.Read<std::string>();
		pTeam->ChangeLeader(playerGuid, playerName);
	}
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandleTeamDisband(MapInstance *pInstance, INetPacket &pck, size_t gsIdx)
{
	pInstance->GetMapTeamManager().DeleteTeam((u16)gsIdx, pck.Read<uint32>());
	return SessionHandleSuccess;
}

int InstancePacketHandler::HandlePlaybossStrike(MapInstance* pInstance, INetPacket& pck, size_t gsIdx)
{
	InstGUID instGuid;
	ObjGUID playerGuid;
	std::string_view playerName;
	uint32 spawnId;
	uint64 loseHP;
	pck >> instGuid >> playerGuid >> playerName >> spawnId >> loseHP;

	LuaTable t;
	t.append(instGuid);
	t.append(playerGuid);
	t.append(playerName);
	t.append(spawnId);
	t.append(loseHP);
	pInstance->MapHookEvent_OnSendMessage("OnPlayerStrike", t);

	return SessionHandleSuccess;
}

int InstancePacketHandler::HandlePlaybossDead(MapInstance* pInstance, INetPacket& pck, size_t gsIdx)
{
	ObjGUID playerGuid;
	std::string_view playerName;
	uint32 spawnId;
	pck >> playerGuid >> playerName >> spawnId;

	LuaTable t;
	t.append(playerGuid);
	t.append(playerName);
	t.append(spawnId);
	pInstance->MapHookEvent_OnSendMessage("OnBossDead", t);

	return SessionHandleSuccess;
}

int InstancePacketHandler::HandlePlaybossStop(MapInstance* pInstance, INetPacket& pck, size_t gsIdx)
{
	bool isSucc;
	pck >> isSucc;

	LuaTable t;
	t.append(isSucc);
	pInstance->MapHookEvent_OnSendMessage("OnActvtStop", t);

	return SessionHandleSuccess;
}
